package com.cauli.file.component;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cauli.file.config.RabbitMQConfig;
import com.cauli.file.mapper.FileMapper;
import com.cauli.file.mapper.MusicMapper;
import com.cauli.file.mapper.UserFileMapper;
import com.cauli.file.model.dto.file.FileSearchDTO;
import com.cauli.file.model.entity.FileEntity;
import com.cauli.file.model.entity.Music;
import com.cauli.file.model.entity.Share;
import com.cauli.file.model.entity.ShareFile;
import com.cauli.file.model.entity.UserFile;
import com.cauli.file.service.ShareFileService;
import com.cauli.file.service.ShareService;
import com.cauli.file.utils.TreeNode;
import com.cauli.file.utils.UserFileUtils;
import com.qiwenshare.common.util.MusicUtils;
import com.qiwenshare.ufop.factory.UFOPFactory;
import com.qiwenshare.ufop.operation.copy.Copier;
import com.qiwenshare.ufop.operation.copy.domain.CopyFile;
import com.qiwenshare.ufop.operation.download.Downloader;
import com.qiwenshare.ufop.operation.download.domain.DownloadFile;
import com.qiwenshare.ufop.operation.write.Writer;
import com.qiwenshare.ufop.operation.write.domain.WriteFile;
import com.qiwenshare.ufop.util.UFOPUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.AudioHeader;
import org.jaudiotagger.audio.flac.FlacFileReader;
import org.jaudiotagger.audio.mp3.MP3File;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.datatype.Artwork;
import org.jaudiotagger.tag.id3.AbstractID3v2Frame;
import org.jaudiotagger.tag.id3.AbstractID3v2Tag;
import org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author Cauli
 * @date 2023-03-20 12:00
 * @description 文件逻辑处理组件
 */
@Slf4j
@Component
public class FileDealComp {
    @Autowired
    private UserFileMapper userFileMapper;

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private ShareService shareService;

    @Autowired
    private ShareFileService shareFileService;

    @Autowired
    private MusicMapper musicMapper;

    @Resource
    private UFOPFactory ufopFactory;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            12, // 核心线程数
            20, // 最大线程数
            1, // 线程存活时间
            TimeUnit.SECONDS, // 存活时间单位
            new ArrayBlockingQueue<>(1000) // 任务队列
    );

    /**
     * 获取重复文件名
     * 场景1: 文件还原时，在 saveFilePath 路径下，保存 测试.txt 文件重名，则会生成 测试(1).txt
     * 场景2： 上传文件时，在 saveFilePath 路径下，保存 测试.txt 文件重名，则会生成 测试(1).txt
     *
     * @param userFile
     * @param saveFilePath
     * @return
     */
    public String getRepeatFileName(UserFile userFile, String saveFilePath) {
        String fileName = userFile.getFileName();
        String extendName = userFile.getExtendName();
        Integer deleted = userFile.getDeleted();
        Integer deleteFlag = userFile.getDeleteFlag();
        Long userId = StpUtil.getLoginIdAsLong();

        int isDir = userFile.getIsDir();
        LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserFile::getFilePath, saveFilePath)
                .eq(UserFile::getUserId, userId)
                .eq(UserFile::getFileName, fileName)
                .eq(UserFile::getIsDir, isDir)
                .eq(UserFile::getDeleted, deleted)
                .eq(UserFile::getDeleteFlag, deleteFlag);
        if (userFile.getIsDir() == 0) {
            lambdaQueryWrapper.eq(UserFile::getExtendName, extendName);
        }
        List<UserFile> list = userFileMapper.selectList(lambdaQueryWrapper);
        if (list == null || list.isEmpty()) {
            return fileName;
        }

        int i = 0;
        while (!CollectionUtil.isEmpty(list)) {
            i++;
            LambdaQueryWrapper<UserFile> lambdaQueryRepeatWrapper = new LambdaQueryWrapper<>();
            lambdaQueryRepeatWrapper
                    .eq(UserFile::getFilePath, saveFilePath)
                    .eq(UserFile::getUserId, userId)
                    .eq(UserFile::getFileName, fileName + "(" + i + ")")
                    .eq(UserFile::getIsDir, isDir)
                    .eq(UserFile::getDeleted, deleted)
                    .eq(UserFile::getDeleteFlag, deleteFlag);
            if (userFile.getIsDir() == 0) {
                lambdaQueryRepeatWrapper.eq(UserFile::getExtendName, extendName);
            }
            list = userFileMapper.selectList(lambdaQueryRepeatWrapper);
        }
        return fileName + "(" + i + ")";
    }

    /**
     * 还原父文件路径
     * 1、回收站文件还原操作会将文件恢复到原来的路径下,当还原文件的时候，如果父目录已经不存在了，则需要把父目录给还原
     * 2、上传目录
     *
     * @param userId
     */
    public void restoreParentFilePath(FileComponent fileComponent, Long userId) {
        if (fileComponent.isFile()) {
            fileComponent = fileComponent.getParentFile();
        }
        while (fileComponent.getParent() != null) {
            String fileName = fileComponent.getName();
            String parentFilePath = fileComponent.getParent();

            LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(UserFile::getFilePath, parentFilePath)
                    .eq(UserFile::getFileName, fileName)
                    .eq(UserFile::getIsDir, 1)
                    .eq(UserFile::getUserId, userId)
                    .eq(UserFile::getDeleted, 0)
                    .eq(UserFile::getDeleteFlag, 1);
            List<UserFile> userFileList = userFileMapper.selectList(lambdaQueryWrapper);
            if (userFileList.size() == 0) {
                UserFile userFile = UserFileUtils.getUserDir(userId, parentFilePath, fileName);
                try {
                    synchronized (this) {
                        LambdaQueryWrapper<UserFile> userFileLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        userFileLambdaQueryWrapper.eq(userFile.getUserFileId() != null, UserFile::getUserFileId, userFile.getUserFileId())
                                .eq(StrUtil.isNotBlank(userFile.getFileName()), UserFile::getFileName, userFile.getFileName())
                                .eq(StrUtil.isNotBlank(userFile.getFilePath()), UserFile::getFilePath, userFile.getFilePath())
                                .eq(userFile.getIsDir() != null, UserFile::getIsDir, userFile.getIsDir());
                        UserFile isRepeatUserFile = userFileMapper.selectOne(userFileLambdaQueryWrapper);
                        if (isRepeatUserFile == null) {
                            userFileMapper.insert(userFile);
                        }
                    }
                } catch (Exception e) {
                    if (e.getMessage().contains("Duplicate entry")) {
                    } else {
                        log.error(e.getMessage());
                    }
                }
            }
            fileComponent = new FileComponent(parentFilePath, true);
        }
    }


    /**
     * 删除重复的子目录文件
     * 当还原目录的时候，如果其子目录在文件系统中已存在，则还原之后进行去重操作
     *
     * @param filePath
     * @param userId
     */
    public void deleteRepeatSubDirFile(String filePath, Long userId) {
        log.debug("删除子目录：" + filePath);
        LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(UserFile::getFileName, UserFile::getFilePath)
                .likeRight(UserFile::getFilePath, UserFileUtils.formatLikePath(filePath))
                .eq(UserFile::getIsDir, 1)
                .eq(UserFile::getUserId, userId)
                .eq(UserFile::getDeleted, 0)
                .eq(UserFile::getDeleteFlag, 0)
                .groupBy(UserFile::getFilePath, UserFile::getFileName)
                .having("count(file_name) >= 2");
        List<UserFile> repeatList = userFileMapper.selectList(lambdaQueryWrapper);

        for (UserFile userFile : repeatList) {
            LambdaQueryWrapper<UserFile> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper1.eq(UserFile::getFilePath, userFile.getFilePath())
                    .eq(UserFile::getFileName, userFile.getFileName())
                    .eq(UserFile::getDeleted, 0)
                    .eq(UserFile::getDeleteFlag, 0);
            List<UserFile> userFiles = userFileMapper.selectList(lambdaQueryWrapper1);
            for (int i = 0; i < userFiles.size() - 1; i++) {
                userFileMapper.deleteById(userFiles.get(i).getUserFileId());
            }
        }
    }

    /**
     * 组织一个树目录节点，文件移动的时候使用
     *
     * @param treeNode
     * @param id
     * @param filePath
     * @param nodeNameQueue
     * @return
     */
    public TreeNode insertTreeNode(TreeNode treeNode, long id, String filePath, Queue<String> nodeNameQueue) {
        List<TreeNode> childrenTreeNodes = treeNode.getChildren();
        String currentNodeName = nodeNameQueue.peek();
        if (currentNodeName == null) {
            return treeNode;
        }

        FileComponent fileComponent = new FileComponent(filePath, currentNodeName, true);
        filePath = fileComponent.getPath();

        // 1、判断有没有该子节点，如果没有则插入
        if (!isExistPath(childrenTreeNodes, currentNodeName)) {
            //插入
            TreeNode resultTreeNode = new TreeNode();

            resultTreeNode.setFilePath(filePath);
            resultTreeNode.setLabel(nodeNameQueue.poll());
            resultTreeNode.setId(++id);

            childrenTreeNodes.add(resultTreeNode);
        } else {
            // 2、如果有，则跳过
            nodeNameQueue.poll();
        }

        if (nodeNameQueue.size() != 0) {
            for (int i = 0; i < childrenTreeNodes.size(); i++) {

                TreeNode childrenTreeNode = childrenTreeNodes.get(i);
                if (currentNodeName.equals(childrenTreeNode.getLabel())) {
                    childrenTreeNode = insertTreeNode(childrenTreeNode, id * 10, filePath, nodeNameQueue);
                    childrenTreeNodes.remove(i);
                    childrenTreeNodes.add(childrenTreeNode);
                    treeNode.setChildren(childrenTreeNodes);
                }

            }
        } else {
            treeNode.setChildren(childrenTreeNodes);
        }

        return treeNode;

    }

    /**
     * 判断该路径在树节点中是否已经存在
     *
     * @param childrenTreeNodes
     * @param path
     * @return
     */
    public boolean isExistPath(List<TreeNode> childrenTreeNodes, String path) {
        boolean isExistPath = false;

        try {
            for (int i = 0; i < childrenTreeNodes.size(); i++) {
                if (path.equals(childrenTreeNodes.get(i).getLabel())) {
                    isExistPath = true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return isExistPath;
    }

    /**
     * 根据用户传入的参数，判断是否有下载或者预览权限
     *
     * @return
     */
    public boolean checkAuthDownloadAndPreview(String shareBatchNum,
                                               String extractionCode,
                                               String token,
                                               Long userFileId,
                                               Integer platform) {
        log.debug("权限检查开始：shareBatchNum:{}, extractionCode:{}, token:{}, userFileId{}", shareBatchNum, extractionCode, token, userFileId);
        if (platform != null && platform == 2) {
            return true;
        }
        UserFile userFile = userFileMapper.selectById(userFileId);
        log.debug(JSON.toJSONString(userFile));
        if ("undefined".equals(shareBatchNum) || StringUtils.isEmpty(shareBatchNum)) {

            Long userId = StpUtil.getLoginIdAsLong();
            log.debug(JSON.toJSONString("当前登录用户id：" + userId));
            log.debug("文件所属用户id：" + userFile.getUserId());
            if (!userFile.getUserId().equals(userId)) {
                log.info("用户id不一致，权限校验失败");
                return false;
            }
        } else {
            Map<String, Object> param = new HashMap<>();
            param.put("share_batch_num", shareBatchNum);
            List<Share> shareList = shareService.listByMap(param);
            //判断批次号
            if (shareList.size() <= 0) {
                log.info("分享批次号不存在，权限校验失败");
                return false;
            }
            Integer shareType = shareList.get(0).getShareType();
            if (1 == shareType) {
                //判断提取码
                if (!shareList.get(0).getExtractionCode().equals(extractionCode)) {
                    log.info("提取码错误，权限校验失败");
                    return false;
                }
            }
            param.put("user_file_id", userFileId);
            List<ShareFile> shareFileList = shareFileService.listByMap(param);
            if (shareFileList.size() <= 0) {
                log.info("用户id和分享批次号不匹配，权限校验失败");
                return false;
            }
        }
        return true;
    }

    /**
     * 拷贝文件
     * 场景：修改的文件被多处引用时，需要重新拷贝一份，然后在新的基础上修改
     *
     * @param fileEntity
     * @param userFile
     * @return
     */
    public String copyFile(FileEntity fileEntity, UserFile userFile) {
        Copier copier = ufopFactory.getCopier();
        Downloader downloader = ufopFactory.getDownloader(fileEntity.getStorageType());
        DownloadFile downloadFile = new DownloadFile();
        downloadFile.setFileUrl(fileEntity.getFileUrl());
        CopyFile copyFile = new CopyFile();
        copyFile.setExtendName(userFile.getExtendName());
        String fileUrl = copier.copy(downloader.getInputStream(downloadFile), copyFile);
        if (downloadFile.getOssClient() != null) {
            downloadFile.getOssClient().shutdown();
        }
        fileEntity.setFileUrl(fileUrl);
        fileMapper.insert(fileEntity);
        userFile.setFileId(fileEntity.getFileId());
        userFileMapper.updateById(userFile);
        return fileUrl;
    }

    /**
     * 获得文件MD5
     *
     * @param fileUrl
     * @param storageType
     * @return
     * @throws IOException
     */
    public String getIdentifierByFile(String fileUrl, int storageType) throws IOException {
        DownloadFile downloadFile = new DownloadFile();
        downloadFile.setFileUrl(fileUrl);
        InputStream inputStream = ufopFactory.getDownloader(storageType).getInputStream(downloadFile);
        String md5Str = DigestUtils.md5Hex(inputStream);
        return md5Str;
    }

    /**
     * 保存文件输入流
     *
     * @param storageType
     * @param fileUrl
     * @param inputStream
     * @throws IOException
     */
    public void saveFileInputStream(int storageType, String fileUrl, InputStream inputStream) throws IOException {
        Writer writer = ufopFactory.getWriter(storageType);
        WriteFile writeFile = new WriteFile();
        writeFile.setFileUrl(fileUrl);
        int fileSize = inputStream.available();
        writeFile.setFileSize(fileSize);
        writer.write(inputStream, writeFile);
    }

    /**
     * 查询是否有同名文件夹
     *
     * @param fileName
     * @param filePath
     * @param userId
     * @return
     */
    public boolean isDirExist(String fileName, String filePath, Long userId) {
        LambdaQueryWrapper<UserFile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserFile::getFileName, fileName)
                .eq(UserFile::getFilePath, FileComponent.formatPath(filePath))
                .eq(UserFile::getUserId, userId)
                .eq(UserFile::getIsDir, 1)
                .eq(UserFile::getDeleted, 0)
                .eq(UserFile::getDeleteFlag, 0);
        List<UserFile> list = userFileMapper.selectList(lambdaQueryWrapper);
        if (!CollectionUtil.isEmpty(list)) {
            return true;
        }
        return false;
    }

    /**
     * 解析音乐文件
     *
     * @param extendName
     * @param storageType
     * @param fileUrl
     * @param fileId
     */
    public void parseMusicFile(String extendName, int storageType, String fileUrl, Long fileId) {
        File outFile = null;
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            if ("mp3".equalsIgnoreCase(extendName) || "flac".equalsIgnoreCase(extendName)) {
                Downloader downloader = ufopFactory.getDownloader(storageType);
                DownloadFile downloadFile = new DownloadFile();
                downloadFile.setFileUrl(fileUrl);
                inputStream = downloader.getInputStream(downloadFile);
                outFile = UFOPUtils.getTempFile(fileUrl);
                if (!outFile.exists()) {
                    outFile.createNewFile();
                }
                fileOutputStream = new FileOutputStream(outFile);
                IOUtils.copy(inputStream, fileOutputStream);
                Music music = new Music();
                music.setFileId(fileId);

                Tag tag = null;
                AudioHeader audioHeader = null;
                if ("mp3".equalsIgnoreCase(extendName)) {
                    MP3File f = (MP3File) AudioFileIO.read(outFile);
                    tag = f.getTag();
                    audioHeader = f.getAudioHeader();
                    MP3File mp3file = new MP3File(outFile);
                    if (mp3file.hasID3v2Tag()) {
                        AbstractID3v2Tag id3v2Tag = mp3file.getID3v2TagAsv24();
                        AbstractID3v2Frame frame = (AbstractID3v2Frame) id3v2Tag.getFrame("APIC");
                        FrameBodyAPIC body;
                        if (frame != null && !frame.isEmpty()) {
                            body = (FrameBodyAPIC) frame.getBody();
                            byte[] imageData = body.getImageData();
                            music.setAlbumImage(Base64.getEncoder().encodeToString(imageData));
                        }
                        if (tag != null) {
                            music.setArtist(tag.getFirst(FieldKey.ARTIST));
                            music.setTitle(tag.getFirst(FieldKey.TITLE));
                            music.setAlbum(tag.getFirst(FieldKey.ALBUM));
                            music.setYear(tag.getFirst(FieldKey.YEAR));
                            try {
                                music.setTrack(tag.getFirst(FieldKey.TRACK));
                            } catch (Exception e) {
                                // ignore
                            }

                            music.setGenre(tag.getFirst(FieldKey.GENRE));
//                            music.setComment(tag.getFirst(FieldKey.COMMENT));
                            music.setLyrics(tag.getFirst(FieldKey.LYRICS));
                            music.setComposer(tag.getFirst(FieldKey.COMPOSER));
                            music.setAlbumArtist(tag.getFirst(FieldKey.ALBUM_ARTIST));
                            music.setEncoder(tag.getFirst(FieldKey.ENCODER));
                        }
                    }
                } else if ("flac".equalsIgnoreCase(extendName)) {
                    AudioFile f = new FlacFileReader().read(outFile);
                    tag = f.getTag();
                    audioHeader = f.getAudioHeader();
                    if (tag != null) {
                        music.setArtist(StringUtils.join(tag.getFields(FieldKey.ARTIST), ","));
                        music.setTitle(StringUtils.join(tag.getFields(FieldKey.TITLE), ","));
                        music.setAlbum(StringUtils.join(tag.getFields(FieldKey.ALBUM), ","));
                        music.setYear(StringUtils.join(tag.getFields(FieldKey.YEAR), ","));
                        music.setTrack(StringUtils.join(tag.getFields(FieldKey.TRACK), ","));
                        music.setGenre(StringUtils.join(tag.getFields(FieldKey.GENRE), ","));
                        music.setComment(StringUtils.join(tag.getFields(FieldKey.COMMENT), ","));
                        music.setLyrics(StringUtils.join(tag.getFields(FieldKey.LYRICS), ","));
                        music.setComposer(StringUtils.join(tag.getFields(FieldKey.COMPOSER), ","));
                        music.setAlbumArtist(StringUtils.join(tag.getFields(FieldKey.ALBUM_ARTIST), ","));
                        music.setEncoder(StringUtils.join(tag.getFields(FieldKey.ENCODER), ","));
                        List<Artwork> artworkList = tag.getArtworkList();
                        if (artworkList != null && !artworkList.isEmpty()) {
                            Artwork artwork = artworkList.get(0);
                            byte[] binaryData = artwork.getBinaryData();
                            music.setAlbumImage(Base64.getEncoder().encodeToString(binaryData));
                        }
                    }
                }
                if (audioHeader != null) {
                    music.setTrackLength(Float.parseFloat(audioHeader.getTrackLength() + ""));
                }
                if (StringUtils.isEmpty(music.getLyrics())) {
                    try {
                        String lyc = MusicUtils.getLyc(music.getArtist(), music.getTitle(), music.getAlbum());
                        music.setLyrics(lyc);
                    } catch (Exception e) {
                        log.info(e.getMessage());
                    }
                }
                musicMapper.insert(music);
            }
        } catch (Exception e) {
            log.error("解析音乐信息失败！", e);
        } finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(fileOutputStream);
            if (outFile != null) {
                if (outFile.exists()) {
                    outFile.delete();
                }
            }
        }
    }

    /**
     * 更新ES数据
     *
     * @param userFileId
     */
    public void uploadES(Long userFileId) {
        threadPoolExecutor.execute(() -> {
            // 用户用户文件ID查询用户文件信息
            Map<String, Object> userFileIdMap = new HashMap<>(1);
            userFileIdMap.put("user_file_id", userFileId);
            List<UserFile> userFileResult = userFileMapper.selectByMap(userFileIdMap);
            if (!CollectionUtil.isEmpty(userFileResult)) {
                FileSearchDTO fileSearchDTO = new FileSearchDTO();
                // 更新用户文件信息
                BeanUtil.copyProperties(userFileResult.get(0), fileSearchDTO);

                // 通过文件ID查询文件信息
                Map<String, Object> fileIdMap = new HashMap<>(1);
                fileIdMap.put("file_id", userFileResult.get(0).getFileId());
                List<FileEntity> fileResult = fileMapper.selectByMap(fileIdMap);
                if (!CollectionUtil.isEmpty(fileResult)) {
                    // 更新文件信息
                    BeanUtil.copyProperties(fileResult.get(0), fileSearchDTO);
                }

                // 消息队列更新ES
                rabbitTemplate.convertAndSend(RabbitMQConfig.FILE_EXCHANGE, RabbitMQConfig.KEY_FILE_SAVE, fileSearchDTO);
            }
        });
    }

    /**
     * 删除ES数据
     *
     * @param userFileId
     */
    public void deleteES(Long userFileId) {
        // 消息队列删除ES
        rabbitTemplate.convertAndSend(RabbitMQConfig.FILE_EXCHANGE, RabbitMQConfig.KEY_FILE_REMOVE, userFileId);
    }

    /**
     * 分享文件过期处理
     *
     * @param shareBatchNum 分享批次号
     */
    public void expiredShareFile(String shareBatchNum) {
        // 根据分享批次号获取分享信息
        LambdaQueryWrapper<Share> shareLambdaQueryWrapper = new LambdaQueryWrapper<>();
        shareLambdaQueryWrapper.eq(StrUtil.isNotEmpty(shareBatchNum), Share::getShareBatchNum, shareBatchNum);
        Share share = shareService.getOne(shareLambdaQueryWrapper);
        // 定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long differenceInMillis = 0;
        try {
            // 解析日期字符串为日期对象
            Date shareDate = sdf.parse(share.getShareTime());
            Date endDate = sdf.parse(share.getEndTime());
            // 计算时间差（毫秒数）
            differenceInMillis = endDate.getTime() - shareDate.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // 存活时间
        String expiration = Long.toString(differenceInMillis);
        // 延时队列
        rabbitTemplate.convertAndSend(RabbitMQConfig.DELAY_QUEUE, share, message -> {
            message.getMessageProperties().setExpiration(expiration);
            return message;
        });
    }
}
